Don't error with checkMissingCallableSignature: true about degraded closures#4823
Don't error with checkMissingCallableSignature: true about degraded closures#4823staabm wants to merge 13 commits intophpstan:2.1.xfrom
checkMissingCallableSignature: true about degraded closures#4823Conversation
|
We could raise the threshold to degenerate later.. need to test this in the origin slow snippets though |
|
An idea - we could degrade it only for literal array in code, but we wouldn't need to degrade it for array shapes? Meaning ConstantArrayTypeBuilder in TypeNodeResolver would be created in a different mode. Also maybe the limit for degrading closures could be higher? |
I don't see how this is possible, because the worst case scenario is built up over one assign per line |
|
I had to discard the previous fix because it discarded all perf benefits we got previosuly with #4684 |
|
This pull request has been marked as ready for review. |
|
sorry for flooding this PR with commits/pushes |
|
This pull request has been marked as ready for review. |
How about this one: diff --git a/src/PhpDoc/TypeNodeResolver.php b/src/PhpDoc/TypeNodeResolver.php
index 4df978002..979977508 100644
--- a/src/PhpDoc/TypeNodeResolver.php
+++ b/src/PhpDoc/TypeNodeResolver.php
@@ -1050,6 +1050,13 @@ final class TypeNodeResolver
$builder->degradeToGeneralArray(true);
}
+ foreach ($typeNode->items as $itemNode) {
+ if ($itemNode->valueType instanceof CallableTypeNode) {
+ $builder->degradeClosures(false); // explicit opt-out of closure degradation
+ break;
+ }
+ }
+
foreach ($typeNode->items as $itemNode) {
$offsetType = $this->resolveArrayShapeOffsetType($itemNode, $nameScope);
$builder->setOffsetValueType($offsetType, $this->resolve($itemNode->valueType, $nameScope), $itemNode->optional);
diff --git a/src/Type/Constant/ConstantArrayTypeBuilder.php b/src/Type/Constant/ConstantArrayTypeBuilder.php
index 9396fec39..3d7005e93 100644
--- a/src/Type/Constant/ConstantArrayTypeBuilder.php
+++ b/src/Type/Constant/ConstantArrayTypeBuilder.php
@@ -35,7 +35,7 @@ final class ConstantArrayTypeBuilder
private bool $degradeToGeneralArray = false;
- private bool $degradeClosures = false;
+ private ?bool $degradeClosures = false;
private bool $oversized = false;
@@ -94,7 +94,7 @@ final class ConstantArrayTypeBuilder
$numClosures++;
}
- if ($numClosures >= self::CLOSURES_COUNT_LIMIT) {
+ if ($numClosures >= self::CLOSURES_COUNT_LIMIT && $this->degradeClosures !== false) {
$this->degradeClosures = true;
$this->degradeToGeneralArray = true;
$this->oversized = true;
@@ -300,6 +300,15 @@ final class ConstantArrayTypeBuilder
$this->oversized = $this->oversized || $oversized;
}
+ /**
+ * @param bool|null $degrade Use `null` to auto-detect based on closures count;
+ * Use boolean to explicitly enable/disable closure degradation.
+ */
+ public function degradeClosures(?bool $degrade = false): void
+ {
+ $this->degradeClosures = $degrade;
+ }
+
public function getArray(): Type
{
$keyTypesCount = count($this->keyTypes);
On my laptop, it is a steady ~3.02 seconds before/after this patch. |
edit: found the typo in your suggestion :) |
Co-Authored-By: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com>
|
should be good to go. thank you both |
closes phpstan/phpstan#14012
Updated Description
after this PR we still have errors when callables have been degraded, but as we degrade less often/later this should be less of a problem.
I also checked the reproducers of #4684 so they are equal fast.
In addition we no longer degrade callables when defined in a phpdoc array shape.